#include "util.hpp"
#include "config.hpp"
#include "data.hpp"
#include "hot.hpp"
#include "service.hpp"
#include "./logs/bin.hpp"

#include <pthread.h>

void FileUtilTest1(const std::string &filename)
{
    cloud::FileUtil fu(filename);
    std::cout << fu.FileSize() << std::endl;
    std::cout << fu.LastMTime() << std::endl;
    std::cout << fu.LastATime() << std::endl;
    std::cout << fu.FileName() << std::endl;
}

void FileUtilTest2(const std::string &filename)
{
    cloud::FileUtil fu(filename);

    std::string body;

    fu.GetContent(&body);

    cloud::FileUtil nfu("./hello.txt");

    nfu.SetContent(body);
}

void FileUtilTest3(const std::string &filename)
{
    cloud::FileUtil fu(filename);
    fu.Compress(filename + ".lz");

    cloud::FileUtil pfu(filename + ".lz");
    pfu.UnCompress(filename + "cpoy");
}

void FileUtilTest4(const std::string &filename)
{
    cloud::FileUtil fu(filename);
    fu.CreateDirectory();
    std::vector<std::string> arry;
    fu.ScanDirectory(&arry);

    for (auto &a : arry)
    {
        std::cout << a << std::endl;
    }
}

void JsonUtilTest()
{
    const char *name = "小明";
    int age = 19;
    float score[] = {85, 69, 94};
    Json::Value root;
    root["姓名"] = name;
    root["年龄"] = age;
    root["成绩"].append(score[0]);
    root["成绩"].append(score[1]);
    root["成绩"].append(score[2]);

    std::string json_str;
    cloud::JsonUtil::Serialize(root, &json_str);

    std::cout << json_str << std::endl;
    Json::Value ret;
    cloud::JsonUtil::Unserialize(json_str, &ret);
    std::cout << root["姓名"].asString() << std::endl;
    std::cout << root["年龄"].asInt() << std::endl;
    for (int i = 0; i < ret["成绩"].size(); i++)
    {
        std::cout << root["成绩"][i].asFloat() << std::endl;
    }
}

void ConfigTest()
{
    cloud::Config *config = cloud::Config::GetInstance();
    std::cout << config->GetHotTime() << std::endl;
    std::cout << config->GetServerPort() << std::endl;
    std::cout << config->GetServerIp() << std::endl;
    std::cout << config->GetDownloadPrefix() << std::endl;
    std::cout << config->GetPackFileSuffix() << std::endl;
    std::cout << config->GetPackDir() << std::endl;
    std::cout << config->GetBackDir() << std::endl;
    std::cout << config->GetBackupFile() << std::endl;
}

void DataTest1(const std::string &filename)
{
    cloud::BackupInfo info;
    if (!info.NewBackupInfo(filename))
        return;

    std::cout << info.pack_flag << std::endl;
    std::cout << info.fsize << std::endl;
    std::cout << info.atime << std::endl;
    std::cout << info.mtime << std::endl;
    std::cout << info.real_path << std::endl;
    std::cout << info.pack_path << std::endl;
    std::cout << info.url << std::endl;
}

void DataTest2(const std::string &filename)
{
    cloud::BackupInfo info;
    if (!info.NewBackupInfo(filename))
        return;

    cloud::DataManager data;
    data.Insert(info);

    std::cout << "----------------GetOneByUrl----------------" << std::endl;

    cloud::BackupInfo tmp;
    data.GetOneByUrl("/download/bundle.h", &tmp);

    std::cout << tmp.pack_flag << std::endl;
    std::cout << tmp.fsize << std::endl;
    std::cout << tmp.atime << std::endl;
    std::cout << tmp.mtime << std::endl;
    std::cout << tmp.real_path << std::endl;
    std::cout << tmp.pack_path << std::endl;
    std::cout << tmp.url << std::endl;

    std::cout << "----------------GetAll----------------" << std::endl;


    info.pack_flag = true;
    data.Updata(info);

    std::vector<cloud::BackupInfo> arry;
    data.GetAll(&arry);
    for (auto &a : arry)
    {
        std::cout << a.pack_flag << std::endl;
        std::cout << a.fsize << std::endl;
        std::cout << a.atime << std::endl;
        std::cout << a.mtime << std::endl;
        std::cout << a.real_path << std::endl;
        std::cout << a.pack_path << std::endl;
        std::cout << a.url << std::endl;
    }

    std::cout << "---------------GetOneByRealpath-----------------" << std::endl;

    data.GetOneByRealpath(filename, &tmp);

    std::cout << tmp.pack_flag << std::endl;
    std::cout << tmp.fsize << std::endl;
    std::cout << tmp.atime << std::endl;
    std::cout << tmp.mtime << std::endl;
    std::cout << tmp.real_path << std::endl;
    std::cout << tmp.pack_path << std::endl;
    std::cout << tmp.url << std::endl;

    data.Storage();
}

void DataTest3(const std::string &filename)
{
    cloud::DataManager data;
    std::vector<cloud::BackupInfo> arry;
    data.GetAll(&arry);
    for (auto &a : arry)
    {
        std::cout << a.pack_flag << std::endl;
        std::cout << a.fsize << std::endl;
        std::cout << a.atime << std::endl;
        std::cout << a.mtime << std::endl;
        std::cout << a.real_path << std::endl;
        std::cout << a.pack_path << std::endl;
        std::cout << a.url << std::endl;
    }
}

cloud::DataManager* _data;
void HotTest()
{
    bin::Logger::ptr logger =  bin::getLogger("cloud");
    logger->info("HotTest is runing");
    cloud::HotManager hot;
    hot.RunModule();
}

void ServiceTest()
{
    bin::Logger::ptr logger =  bin::getLogger("cloud");
    logger->info("ServiceTest is runing");
    cloud::Service srv;
    srv.RunModule();
}

int main(int argc, char *argv[])
{
    std::unique_ptr<bin::LoggerBuilder> builder(new bin::GlobalLoggerBuilder());
    builder->buildLoggerName("cloud");
    builder->buildLoggerLevel(bin::LogLevel::value::INFO);
    builder->buildFormatter("[%c][%f:%l]%m%n");
    builder->buildLoggerType(bin::LoggerType::LOGGER_SYNC);
    builder->buildSink<bin::StdoutSink>();
    builder->buildSink<bin::FileSink>("./logfile/log.txt");
    builder->build();

    _data = new cloud::DataManager();
    
    std::thread thread_hot_manage(HotTest);
    std::thread thread_service(ServiceTest);
    thread_hot_manage.join();
    thread_service.join();
    return 0;
}